package com.cygsunri.wisdompark.callback.service;

import com.cygsunri.wisdompark.callback.entity.HisAnalogs;
import org.apache.commons.lang3.StringUtils;
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class InfluxDBService {

    @Value("${spring.influxDB.name}")
    private String influxDBName;

    @Value("${spring.influxDB.host}")
    private String influxDBHost;

    @Value("${spring.influxDB.port}")
    private Integer influxDBPort;

    private InfluxDB influxDB;

    @PostConstruct
    public void init() {
        influxDB = InfluxDBFactory.connect("http://" + influxDBHost + ":" + influxDBPort, "root", "root");
        influxDB.setDatabase(influxDBName).enableBatch(5000, 1000, TimeUnit.MILLISECONDS);
    }

    @PreDestroy
    public void destroy() {
        influxDB.close();
    }


    /**
     * 存数据至analogs
     */
    public void saveAnalogs(String code, Double data, long time) {
        influxDB.write(Point.measurement("analogs")
                .time(time, TimeUnit.MILLISECONDS)
                .tag("code", code)
                .addField("data", data)
                .build());
    }

    /**
     * 存数据至events
     */
    public void saveEvents(String code, Double data, long time, int source) {
        influxDB.write(Point.measurement("events")
                .time(time, TimeUnit.MILLISECONDS)
                .tag("code", code)
                .addField("data", data)
                .addField("soe", source)
                .build());
    }

//    /**
//     * 批量存数据至analogs
//     */
//    public void saveAnalogs(List<DataTemp> dataTemps) {
//        BatchPoints batchPoints = BatchPoints
//                .database(influxDBName)
//                .consistency(InfluxDB.ConsistencyLevel.ALL)
//                .build();
//
//        dataTemps.forEach(dataTemp -> {
//            String code = cacheService.getCodeMapping(dataTemp.getType(), dataTemp.getRtuNo(), dataTemp.getDataNo());
//            if (code == null || dataTemp.getType() == 1) { //总招遥信不存突变表
//                return;
//            }
//            Point point = Point.measurement("analogs")
//                    .time(dataTemp.getTime(), TimeUnit.MILLISECONDS)
//                    .tag("code", code)
//                    .addField("data", dataTemp.getData())
//                    .build();
//            batchPoints.point(point);
//        });
//        influxDB.write(batchPoints);
//    }


    /**
     * 批量存数据至hisAnalogs
     */
    public void saveHisAnalogs(Map<String, String> map) {
        BatchPoints batchPoints = BatchPoints
                .database(influxDBName)
                .consistency(InfluxDB.ConsistencyLevel.ALL)
                .build();

        LocalDateTime l = LocalDateTime.now().withSecond(0).withNano(0);

        map.forEach((k, v) -> {
            Point point = Point.measurement("hisAnalogs")
                    .time(l.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), TimeUnit.MILLISECONDS)
                    .tag("code", k)
                    .addField("data", Double.parseDouble(v))
                    .build();
            batchPoints.point(point);
        });
        influxDB.write(batchPoints);
    }


//
//
//    /**
//     * 批量存数据至hisAnalogs
//     */
//    public void saveHisAnalogs(String id,Map map) {
//        BatchPoints batchPoints = BatchPoints
//                .database(influxDBName)
//                .consistency(InfluxDB.ConsistencyLevel.ALL)
//                .build();
//
//        LocalDateTime l = LocalDateTime.now().withSecond(0).withNano(0);
//
//        map.forEach((k, v) -> {
//            Point point = Point.measurement("hisAnalogs")
//                    .time(l.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(), TimeUnit.MILLISECONDS)
//                    .tag("code", id+"_"+k)
//                    .addField("data", v.toString())
//                    .build();
//            batchPoints.point(point);
//        });
//        influxDB.write(batchPoints);
//    }

    /**
     * 查询电表数据表中
     */
    public List<HisAnalogs> queryHisAnalogs(String id, String name) {
        String command;
        if(StringUtils.isEmpty(name)||"all".equals(name)){
            command = "select * from hisAnalogs where time > now() - 7d and code =~ /^"+id+"/ order by time asc  tz('Asia/Shanghai')";
        }else{
            command = "select * from hisAnalogs where time > now() - 7d and code = '"+id+"_"+name+"' order by time asc  tz('Asia/Shanghai')";
        }
        QueryResult results = influxDB.query(new Query(command));
        List<HisAnalogs> lists = new ArrayList<HisAnalogs>();
        for (QueryResult.Result result : results.getResults()) {
            List<QueryResult.Series> series= result.getSeries();
            for (QueryResult.Series serie : series) {
                List<List<Object>>  values = serie.getValues();
                List<String> columns = serie.getColumns();
                lists.addAll(getQueryData(columns, values));
            }
        }
        return lists;
    }



    /***整理列名、行数据***/
    private List<HisAnalogs> getQueryData(List<String> columns, List<List<Object>>  values){
        List<HisAnalogs> lists = new ArrayList<HisAnalogs>();
        for (List<Object> list : values) {
            HisAnalogs info = new HisAnalogs();
            BeanWrapperImpl bean = new BeanWrapperImpl(info);
            for(int i=0; i< list.size(); i++){
                String propertyName = setColumns(columns.get(i));//字段名
                Object value = list.get(i);//相应字段值
                bean.setPropertyValue(propertyName, value);
            }
            lists.add(info);
        }
        return lists;
    }


    /***转义字段***/
    private String setColumns(String column){
        String[] cols = column.split("_");
        StringBuffer sb = new StringBuffer();
        for(int i=0; i< cols.length; i++){
            String col = cols[i].toLowerCase();
            if(i != 0){
                String start = col.substring(0, 1).toUpperCase();
                String end = col.substring(1).toLowerCase();
                col = start + end;
            }
            sb.append(col);
        }
        return sb.toString();
    }


}
